<script setup lang="ts">
/**
 * @name ApplicationModels
 * @description 应用模型管理
 */
import ContainerHead from './components/ContainerHead/ContainerHead.vue'
import ModelTableLists from './components/ModelTableLists/ModelTableLists.vue'
import ModelNodeTableLists from './components/ModelNodeTableLists/ModelNodeTableLists.vue'
import NodesTreeOrg from './components/NodesTreeOrg/NodesTreeOrg.vue'

import ModelDialog from './components/ModelDialog/ModelDialog.vue'
import NodeDialog from './components/NodeDialog/NodeDialog.vue'

import { useModelLists } from './ApplicationModels'
import type { ApplicationModel } from '@/types/modules/application-models'

import { CopyFromEnergyUnits, type CopyFromEnergyUnitsInstance } from './components/CopyFromEnergyUnits'

const modelRef
  = ref<InstanceType<typeof ModelTableLists>>()
const modelDialog = ref<InstanceType<typeof ModelDialog>>()
const nodeDialog = ref<InstanceType<typeof NodeDialog>>()
const copyFromEnergyUnitsRef = ref<CopyFromEnergyUnitsInstance>()

const modelDialogTitle = ref('')
const nodeDialogTitle = ref('')
const model: ApplicationModel = reactive({
  id: 0,
  parentId: 0,
  name: '',
  code: '',
})
const node: Omit<ApplicationModel, 'parentId'> & {
  modelId: number
  parentId: number[]
} = reactive({
  id: 0,
  modelId: 0,
  parentId: [],
  name: '',
  code: '',
})

const {
  loading,
  childrenLoading,
  lists,
  children,
  columns,
  setChildren,
  getLists,
  getChildrenById,
  deleteModelOne,
  deleteNodeOne,
} = useModelLists()

const treeData = computed(() => {
  const current = modelRef.value?.current
  if (!current)
    return {}
  return {
    id: 0,
    name: current.name,
    children: unref(children),
  }
})

async function handleModelSelectChange(
  o: ApplicationModel | null,
) {
  if (o && o.id) {
    getChildrenById(o.id)
  }
  else {
    setChildren([])
  }
}

function clickAddModel() {
  Object.assign(model, {
    id: 0,
    parentId: 0,
    name: '',
    code: '',
  })
  modelDialogTitle.value = '新增模型'
  modelDialog.value?.open()
}
function clickEditModel(row: ApplicationModel) {
  Object.assign(model, row)
  modelDialogTitle.value = '编辑模型'
  modelDialog.value?.open()
}
function clickDeleteModel(row: ApplicationModel) {
  deleteModelOne(row.id)
}
function clickAddNode() {
  const current = modelRef.value?.current
  Object.assign(node, {
    id: 0,
    parentId: [],
    name: '',
    code: '',
    modelId: current?.id ?? 0, // 模型
  })
  nodeDialogTitle.value = '新增节点'
  nodeDialog.value?.open()
}
function clickEditNode(row: ApplicationModel) {
  const current = modelRef.value?.current
  // ElCascader组件modelValue是节点路径数组
  const parentId = (row.trees || '')
    .split(',')
    .filter(v => v.length > 0)
    .map(Number)
    .filter(Number.isFinite)
  // 去掉首部“模型ID”
  parentId.shift()
  // 去掉尾部“当前节点ID”
  parentId.pop()

  // 赋值模型ID、父节点ID
  Object.assign(node, row, {
    modelId: current?.id ?? 0,
    parentId,
  })
  nodeDialogTitle.value = '编辑节点'
  nodeDialog.value?.open()
}
function clickDeleteNode(row: ApplicationModel) {
  deleteNodeOne(row.id)
}

function clickLink() {
  copyFromEnergyUnitsRef.value?.open()
}

function nodeSaveSuccess() {
  const current = modelRef.value?.current
  if (current?.id) {
    getChildrenById(current.id)
  }
}

onMounted(() => {
  getLists()
})
</script>

<template>
  <div class="padding-sm flex container">
    <div class="models-container">
      <ContainerHead class="flex-shrink-0" title="应用模型">
        <template #action>
          <ElButton type="primary" @click="clickAddModel">
            新增
          </ElButton>
        </template>
      </ContainerHead>
      <div class="margin-top-sm flex-fillRemaining alpha-block overflow-auto p-[10px]">
        <ModelTableLists
          ref="modelRef"
          :loading="loading"
          :columns="columns"
          :lists="lists"
          @select-change="handleModelSelectChange"
          @edit="clickEditModel"
          @delete="clickDeleteModel"
        />
      </div>
    </div>
    <div class="margin-left-sm nodes-container">
      <ContainerHead class="flex-shrink-0" title="模型节点">
        <template #action>
          <ElLink
            type="primary" class="mx-4" :disabled="!modelRef || !modelRef.current"
            @click="clickLink"
          >
            从用能单元复制
          </ElLink>
          <ElButton type="primary" @click="clickAddNode">
            新增
          </ElButton>
        </template>
      </ContainerHead>
      <div class="margin-top-sm flex-fillRemaining alpha-block overflow-auto p-[10px]">
        <ModelNodeTableLists
          :loading="childrenLoading"
          :lists="children"
          @edit="clickEditNode"
          @delete="clickDeleteNode"
        />
      </div>
    </div>
    <div class="margin-left-sm graph-container">
      <ContainerHead
        class="flex-shrink-0"
        title="模型结构图"
      />
      <div class="margin-top-sm flex-fillRemaining roll border rounded-sm">
        <NodesTreeOrg
          v-if="Object.keys(treeData).length > 0"
          :data="treeData"
        />
      </div>
    </div>
    <ModelDialog
      ref="modelDialog"
      v-model="model"
      :modal-title="modelDialogTitle"
      @save-success="getLists"
    />
    <NodeDialog
      ref="nodeDialog"
      v-model="node"
      :modal-title="nodeDialogTitle"
      :model-lists="lists"
      @save-success="nodeSaveSuccess"
    />

    <!-- 从用能单元复制对话框 -->
    <CopyFromEnergyUnits
      v-if="modelRef?.current"
      ref="copyFromEnergyUnitsRef"
      :model-id="modelRef.current.id"
      @save-success="getChildrenById(modelRef.current.id)"
    />
  </div>
</template>

<style scoped lang="scss">
.models-container,
.nodes-container,
.graph-container {
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.roll {
  @include roll();
}
.models-container {
  flex-basis: 30%;
}
.nodes-container {
  flex-basis: 30%;
}
.graph-container {
  flex: 1;
}
</style>
